home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-12-20 | 5.8 KB | 166 lines | [TEXT/EDIT] |
- Here are two approaches to the RelateSelection procedure, which
- generates a selection of records in a file based on a selection of
- records in a related file. In v3 JOIN and PROJECT SELECTION replace
- this method, though it still has some advantages.
-
-
-
- Procedure RelateSelection (enhanced) 5/20/91
- ______________________________________________
- This is an enhanced version of the recently uploaded RelateSelection. It's
- a little faster overall, and uses arrays to speed up searches on large
- base file selections.
-
- This code will find the records in a file (SearchFile) which are related
- to a selection of records in another file (BaseFile). The files can be
- related one to many, many to one or without drawn relations at all (this
- last is great for creating small indexes (lookup files) for large files).
- So far, when compiled, the code appears to be faster than any other method.
-
- Regarding the array technique, be aware that it requires 4 bytes of RAM
- for each record in the selection.
-
- The progress messages are based on Tech Note No. 206, "Displaying a Custom
- Progress Indicator".
- ______________________________________________
-
- `RelateSelection - enhanced
- `Based on original code by Tony Ringsmuth 6/90
- `Modified 5/91 by Bob Keleher 70451,510 - with contributions
- `and suggestions by Lincoln Stoller and other members of the Acius Forum.
-
- `$1 = >>Search field
- `$2 = >>Base field
-
- C_POINTER($SearchFile;$BaseFile)
- C_LONGINT($Max;$i;$j;$BaseRecs;$LastJ)
- $SearchFile:=File(File($1)) `get pointer to file from field pointer
- $BaseFile:=File(File($2))
- $BaseRecs:=Records in selection($BaseFile>>)
- $Max:=256 `built searches don't like more than 256
- Case of
- : ($BaseRecs=0)
- CREATE EMPTY SET($SearchFile>>;"Related")
- USE SET("Related")
- CLEAR SET("Related")
- : ($BaseRecs<=$Max)
- `Setup progress indicator here e.g. Progress($BaseRecs;"Your
- message")
- FIRST RECORD($BaseFile>>)
- SEARCH($SearchFile>>;$1>>=$2>>;*)
- `Progress(1) `update thermometer
- For ($i;2;$BaseRecs)
- NEXT RECORD($BaseFile>>)
- SEARCH($SearchFile>>; | $1>>=$2>>;*)
- `Progress(1) `update thermometer
- End for
- SEARCH($SearchFile>>)
- `Progress(0) `close progress indicator window
- Else
- `Setup progress indicator here e.g.
- Progress(($BaseRecs\$Max)+1;"Your message")
- $LastJ:=(($BaseRecs\$Max)*$Max)+1 `value of $j at last outer loop
- CREATE EMPTY SET($SearchFile>>;"Related")
- If (Type($2>>)=8) | (Type($2>>)=9) `integer or LongInt
- ARRAY LONGINT(vLIntArray;0)
- SELECTION TO ARRAY($2>>;vLIntArray)
- For ($j;1;$BaseRecs;$Max)
- SEARCH($SearchFile>>;$1>>=vLIntArray{$j};*)
- If ($j=$LastJ) `last outer loop
- $Max:=$BaseRecs-$j+1
- End if
- For ($i;$j+1;$j-1+$Max)
- SEARCH($SearchFile>>; | $1>>=vLintArray{$i};*)
- End for
- SEARCH($SearchFile>>)
- CREATE SET($SearchFile>>;"Relating")
- UNION("Related";"Relating";"Related")
- `Progress(1) `update thermometer
- End for
- CLEAR VARIABLE(vLIntArray)
- Else
- FIRST RECORD($BaseFile>>)
- For ($j;1;$BaseRecs;$Max)
- SEARCH($SearchFile>>;$1>>=$2>>;*)
- If ($j=$LastJ)
- $Max:=$BaseRecs-$j+1
- End if
- For ($i;2;$Max)
- NEXT RECORD($BaseFile>>)
- SEARCH($SearchFile>>; | $1>>=$2>>;*)
- End for
- SEARCH($SearchFile>>)
- CREATE SET($SearchFile>>;"Relating")
- UNION("Related";"Relating";"Related")
- NEXT RECORD($BaseFile>>)
- `Progress(1) `update thermometer
- End for
- End if
- USE SET("Related")
- CLEAR SET("Related")
- CLEAR SET("Relating")
- `Progress(0) `close progress indicator window
- End case
-
-
-
- Date: Thu, 3 Jun 1993 13:01:07 -0800
- From: chuckp@shiva.cac.washington.edu (Chuck Pliske)
- Subject: Re: Join
-
- Bob, (and Bill) I don't have the CI$ discussions archived, but here is the
- relateSelection procedure in all its glory:
-
- Bill, re:
- "In your RelateSelection/built search, do you sort the selection (or
- call SELECTION TO ARRAY, then SORT ARRAY) in order to avoid searching
- for the same value twice?"
-
- No, no sorting, just built searches, for every 250 records of the "input"
- file we build a 250 line search command, then execute it. Note we could
- become server compatible by changing the record loop to create sets of 250
- records and apply to selection as in the top case, thus avoiding the "next
- record" which forces the whole record to be loaded over the net uselessly.
-
- `Procedure RelateSelection
- `it's a good idea to have automatic relations off before running this proc.
- gUserCancel:=False `set up exit test
- ON EVENT CALL("CancelTest")
- START TRANSACTION
- $File1:=File(File($1)) `gets the related records in file 1 for the current
- `selection of file 2
- $File2:=File(File($2))
- If (Records in selection($File2>)<257) `built searches don't like more than 256
- $F1:=$1 `Can't directly use $1 or $2 in Apply to selection
- $F2:=$2
- SEARCH($File1>;$1>=$2>;*)
- APPLY TO SELECTION($File2>;SEARCH($File1>; | $F1>=$F2>;*))
- SEARCH($File1>)
- Else
- CREATE EMPTY SET($file1>;"Related")
- FIRST RECORD($File2>)
- For ($j;1;Records in selection($File2>);250)
- SEARCH($File1>;$1>=$2>;*)
- MESSAGE("Matching "+Filename($File1)+" records to "+Filename($File2)+
- "Records..."+Char(13)+Char(13)+String(Round($j*100/Records in
- selection($File2>);0))+"%")
- $limit:=Lessor (Records in selection($File2>)-Selected record
- number($file2>);250)
- For ($i;1;$limit)
- SEARCH($File1>; | $1>=$2>;*)
- NEXT RECORD($File2>)
- End for
- SEARCH($File1>)
- CREATE SET($File1>;"Relating")
- UNION("Related";"Relating";"Related")
- If (gUserCancel)
- $i:=Records in selection($File2>)+1
- End if
- End for
- USE SET("Related")
- CLEAR SET("Related")
- CLEAR SET("Relating")
- End if
- CANCEL TRANSACTION
- ON EVENT CALL("")
-